package eu.sudparis.it.opp.graph;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Set;

import eu.sudparis.it.opp.Node;

public class Snapshot<T extends Node> {
	public List<Edge> edges = new ArrayList<Edge>();
	public List<T> nodes = new ArrayList<T>();
	
	public Snapshot(Collection<T> observer) {
		this.nodes=new ArrayList<T>(observer);
		for (Node nd : observer) {
			for (Node ndd : nd.inContact) {
				if (this.nodes.contains(ndd)) {
					Edge edge = new Edge(nd.id, ndd.id);
					if (!this.edges.contains(edge))
						this.edges.add(edge);
				}
			}
		}
	}

	public Snapshot() {
		// TODO Auto-generated constructor stub
	}

	public boolean isConnected(int a, int b){
		return this.edges.contains(new Edge(a,b));
	}
	

	
	public List<List<T>> getCliques() {
		List<List<T>> temp = new ArrayList<List<T>>();
		for (int i = 1; i < this.nodes.size(); i++) {
		//	for (int j = i; j < this.nodes.size(); j++) {
				List<T> cand = new ArrayList<T>();
				cand.add(this.nodes.get(i - 1));
				temp.addAll(backTrace(cand, i));
		//	}
		}
		List<List<T>> ret = new ArrayList<List<T>>();
		for(List<T> nods:temp){
			boolean add=false;
			for(List<T> nodss:temp){
				if(nods!=nodss
						&&nods.containsAll(nodss)){
					if(!ret.contains(nods))
						ret.add(nods);
					add=true;
				}else if(nods!=nodss
						&&nodss.containsAll(nods)){
					if(!ret.contains(nodss))
						ret.add(nodss);
					add=true;
				}
			}
			if(!add)
				ret.add(nods);
		}
		return ret;
	}

	private boolean check(List<T> nods, T nod) {
		for (T nd : nods) {
			if (!edges.contains(new Edge(nd.id, nod.id))) {
				return false;
			}
		}
		return true;
	}

	private List<List<T>> backTrace(List<T> candidates, int offset) {
		List<List<T>> temp = new ArrayList<List<T>>();
		if (this.check(candidates, this.nodes.get(offset))) {
			for (int i = offset + 1; i < this.nodes.size(); i++) {
				List<T> ncan = new ArrayList<T>();
				ncan.addAll(candidates);
				ncan.add(this.nodes.get(offset));
				temp.addAll(this.backTrace(ncan, i++));
			}
			if (temp.size() == 0) {
				if (candidates.size() > 1) {
					List<T> ncan = new ArrayList<T>();
					ncan.addAll(candidates);
					ncan.add(this.nodes.get(offset));
					temp.add(ncan);
				}
			}
		}
		return temp;
	}
}
